<script setup>
    import { ref ,onMounted, reactive, onUnmounted,computed,inject,provide} from 'vue'
    import {useRoute} from 'vue-router'
    import RovModel from './RovModel.vue'
    import MjpgVideo from './MjpgVideo.vue'
    import MotorPWM from './MotorPWM.vue'
    import CtlPanel from './CtlPanel.vue'

    const props = defineProps({
        msg: String,
    })

    let route = useRoute()         // 表示当前页面路由信息
    onMounted(()=>{
        console.log("route.query is:", route.query)    //获取路由传入的参数
    })

    const g_ws2 = reactive({
        conn: null
    })
    provide('g_ws2',g_ws2)
    const ws_url= inject('serve_addr') //ref('ws://rqd-ThinkPad-T450:10088/ins_data')
    function connect_serial_proxy(){
        if(null == g_ws2.conn){
            console.log("即将发起ws连接。。。")
            g_ws2.conn = new WebSocket('ws://'+ ws_url.value + ':10088/ins_data')
            g_ws2.conn.onmessage = (evt)=>{
                process_uart4_data(evt)
            }

            comm.value = true
            show_xy.value = true
        }
    }

    onUnmounted(()=>{
        if(g_ws2.conn) g_ws2.conn.close()
    })

    function process_uart4_data(evt){
        //console.log("通过ws收到串口4数据",evt.data)
        const reader = new FileReader()
        reader.onload = (e) => {
            const res = reader.result
            process_msg(new Uint8Array(res))
        }
        reader.readAsArrayBuffer(evt.data)
    }

    function process_msg(msg){
        const dataLen = msg[3]
        if(msg.byteLength - dataLen != 5){
            return //消息被错误的截断，难以避免，直接丢弃不要
        }
        const msgCrc = msg[msg.byteLength-1]
        let chkCrc =0;
        for(let i=0;i<msg.byteLength-1;i++){
            chkCrc +=msg[i]
        }
        chkCrc &= 0xff
        if(msgCrc != chkCrc){
            console.log("消息完整性校验失败!!",chkCrc,msgCrc)
            return
        }

        //console.log("先打印出来看看",msg)
        if(msg[2]==3){  //消息类型3 内容为传感器原始数据
            const data = new Int16Array(msg.buffer,4,3)
            angle.x = data[0]/32768*180;
            angle.y = data[1]/32768*180;
            angle.z = data[2]/32768*180;
            return
        }

        if(msg[2]==4){ //消息类型4 内容为安装误差角度
            const data = new DataView(msg.buffer,4,12)
            offset_angle.x = data.getFloat32(0,true)  // 参数true表示小端字节序
            offset_angle.y = data.getFloat32(4,true)
            offset_angle.z = data.getFloat32(8,true)
            return
        }

        if(msg[2]==5){ //消息类型5 内容为深度
            const data = new DataView(msg.buffer,4,4)
            water_deep.value = data.getFloat32(0,true).toFixed(3)
            //console.log("计算得到水深度",water_deep.value)
            return
        }

        if(msg[2]==0x20){  //消息类型是4个深度电机的PWM值
            const data = new DataView(msg.buffer,4,8)
            pwms.m1 = data.getInt16(0,true)
            pwms.m2 = data.getInt16(2,true)
            pwms.m3 = data.getInt16(4,true)
            pwms.m4 = data.getInt16(6,true)
            return
        }

        if(msg[2]==0x21){ //消息类型是4个运动电机的PWM值
            const data = new Int16Array(msg.buffer,4,4)
            mov_pwms.m5 = data[0]
            mov_pwms.m6 = data[1]
            mov_pwms.m7 = data[2]
            mov_pwms.m8 = data[3]
        }
    }

    function stop_ws_conn(){
        if(g_ws2.conn){
            g_ws2.conn.close()
            g_ws2.conn = null
        }
        comm.value = false
        show_xy.value = false
    }

    const water_deep = ref(-0.1)
    const pwms = reactive({
        m1: 1000,
        m2: 1000,
        m3: 1000,
        m4: 1000
    })
    const mov_pwms = reactive({
        m5:1000,
        m6:1000,
        m7:1000,
        m8:1000
    })
    const angle=reactive({
        x: 0.0,
        y: 0.0,
        z: 0.0
    })

    const offset_angle= reactive({
        x:0.0,
        y:0.0,
        z:0.0
    })
    const rov_dir = computed(()=>{
        let orig_x = angle.x - offset_angle.x
        if(orig_x > 300) orig_x-=360.0
        else if(orig_x < -300) orig_x +=360
        
        let zz = angle.z - offset_angle.z
        if(zz < -300) zz+=360
        else if(zz > 300) zz -=360
        
        return {
            x :  Number(orig_x.toFixed(3)),  //(angle.x - offset_angle.x).toFixed(3),
            y : Number((angle.y - offset_angle.y).toFixed(3)),
            z : Number( zz.toFixed(3))
        }
    })

    const comm = ref(false)
    const show_xy = ref(false)
</script>

<template>
    <div id="flx">
        <MjpgVideo></MjpgVideo>
        <RovModel :rotate_x="rov_dir.x" :rotate_y="rov_dir.y" :rotate_z="rov_dir.z" 
                  :depth="water_deep" :dir_z="rov_dir.z"/>
    </div>
    <div id="control">
        <span id="header">
            数据/指令通道控制：
        </span>
        <button @click="connect_serial_proxy()">打开</button>
        <button @click="stop_ws_conn()">关闭</button>

        <div id="stater">
            <span id="icon_stat" :class="{'bgc-3x':comm }">iiii</span>
            <span v-show="show_xy">x={{angle.x.toFixed(6)}}</span>
            <span v-show="show_xy">y={{angle.y.toFixed(6)}}</span>
        </div>

        <div id="container">
            <div id="tips">运动控制</div>
            <div id="lleft">
                <CtlPanel />
            </div>
            <div id="rright">
                <MotorPWM :mo1="pwms.m1" :mo2="pwms.m2"
                          :mo3="pwms.m3" :mo4="pwms.m4" :start="Number(5)"></MotorPWM>

                <MotorPWM :mo1="mov_pwms.m5" :mo2="mov_pwms.m6"
                          :mo3="mov_pwms.m7" :mo4="mov_pwms.m8" :start="Number(1)"></MotorPWM>
            </div>
        </div>
    </div>
</template>

<style scoped>
.read-the-docs {
    color: #888;
}
#flx{
    margin-top: 1.2em;
    display: flex;
    justify-content:space-around;
}
/* input{
    width: 20em;
    font-size: 1.2em;
} */
#container{
    display: flex;
    justify-content: space-around;
    margin-top: 0.5em;
}
#control button{
    margin: 0 0.6em;
}
span{
    margin: auto 0.9em;
}
/* #container>div{
    border-radius: 8px;
    border: 1px solid #dc2345;
} */
#tips{
    width: 1.3em;
    font-size: 1.1em;
}
#header{
    font-size: 1.1em;
}
#icon_stat{
    margin-left: 2.5em;
    border-radius: 50%;
    /* border: 1px solid red; */
    color:transparent;
    /* box-shadow: 0 0 3px 4px gold; */
}
.bgc-3x {
	-webkit-animation: color-change-3x 1s ease-out infinite alternate both;
	        animation: color-change-3x 1s ease-out infinite alternate both;
          box-shadow: 0 0 3px 4px gold;
}
/* ----------------------------------------------
 * Generated by Animista on 2023-5-26 11:56:22
 * Licensed under FreeBSD License.
 * See http://animista.net/license for more info.
 * w: http://animista.net, t: @cssanimista
 * ---------------------------------------------- */
@-webkit-keyframes color-change-3x {
  0% {
    background: #19dcea;
  }
  50% {
    background: #b22cff;
  }
  100% {
    background: #ea2222;
  }
}
@keyframes color-change-3x {
  0% {
    background: #19fc2a;
  }
  50% {
    background: #f2fc11;
  }
  100% {
    background: #fa2222;
  }
}
#stater{
    display: inline-block;
    border: 1px solid #865463;
    width: 22em;
    text-align: left;
    padding: 4px;
}
</style>
